<template>
    <div>
        <Input
            search
            enter-button
            placeholder="Type path..."
            v-model="path"
            @on-search="search"
        />
        <div class="wrapper">
            <Table
                stripe
                :columns="columns"
                :data="data"
                @on-row-dblclick="click"
            >
                <template slot-scope="{ row }" slot="type">
                    <Icon type="md-folder" v-if="row.type == 'folder'" />
                    <Icon type="ios-document" v-else-if="row.type == 'file'" />
                </template>
                <template slot-scope="{ row }" slot="updated_at">
                    {{
                        row.updated_at == "-"
                            ? "-"
                            : new Date(row.updated_at * 1000).toLocaleString()
                    }}
                </template>
                <template slot-scope="{ row }" slot="action">
                    <Button
                        icon="md-download"
                        type="primary"
                        v-if="row.type == 'file'"
                        @click="download(row)"
                    ></Button>
                    <template
                        v-if="row.name.endsWith('.pom') && row.type == 'file'"
                    >
                        <Button
                            icon="md-information"
                            type="success"
                            @click="maven(row)"
                        ></Button>
                        <Modal
                            v-model="row.open"
                            :title="row.pom.name"
                            :loading="row.loading"
                            :width="680"
                        >
                            {{ row.pom.description }}
                            <div class="code">
                                <pre>
    <span class="code xmltag">&lt;dependencies&gt;</span>
        <span class="code xmltag">&lt;dependency&gt;</span>
            <span class="code xmltag">&lt;groupId&gt;</span>{{row.pom.groupId}}<span class="code xmltag">&lt;/id&gt;</span>
            <span class="code xmltag">&lt;artifactId&gt;</span>{{row.pom.artifactId}}<span class="code xmltag">&lt;/artifactId&gt;</span>
            <span class="code xmltag">&lt;version&gt;</span>{{row.pom.version}}<span class="code xmltag">&lt;/version&gt;</span>
        <span class="code xmltag">&lt;/dependency&gt;</span>
        <span class="code comment">&lt;!-- Other dependencies --&gt;</span>
    <span class="code xmltag">&lt;/dependencies&gt;</span></pre>
                            </div>
                            <div class="modal-action">
                                <Button
                                    type="text"
                                    @click="copy(row, true, 'maven')"
                                    >复制全部</Button
                                >
                                <Button
                                    type="primary"
                                    @click="copy(row, false, 'maven')"
                                    >复制依赖</Button
                                >
                            </div>
                            <div class="code">
                                <pre>
    <span class="code xmltag">compileOnly group: </span>'{{row.pom.groupId}}'<span class="code xmltag">, name: </span>'{{row.pom.artifactId}}'<span class="code xmltag">, version: </span>'{{row.pom.version}}'</pre>
                            </div>
                            <div class="modal-action">
                                <Button
                                    type="primary"
                                    @click="copy(row.pom, false, 'gradle')"
                                    >复制</Button
                                >
                            </div>
                            <div slot="footer"></div>
                        </Modal>
                    </template>
                </template>
            </Table>
            <Spin fix v-if="loading"></Spin>
        </div>
    </div>
</template>
<script>
export default {
    name: "file-browser",
    props: ["repository"],
    methods: {
        click(row, index) {
            if (row.type == "folder") {
                if (row.name == "..") {
                    const stripTrailingSlash = str => {
                        return str.endsWith("/") ? str.slice(0, -1) : str;
                    };
                    this.path = stripTrailingSlash(this.path);
                    var paths = this.path.split("/");
                    paths.pop();
                    this.path = paths.join("/") + "/";
                } else {
                    this.path += row.name + "/";
                }
                if (this.path == "/") this.path = "";
                this.search();
            }
        },
        download(row) {
            this.$Loading.start();
            this.$Notice.info({
                title: "下载中……",
                desc: "请稍等"
            });
            axios
                .get(row.full, { responseType: "blob" })
                .then(response => {
                    this.$Loading.finish();
                    const blob = new Blob([response.data], {
                        type: "application/octet-stream"
                    });
                    const link = document.createElement("a");
                    link.href = URL.createObjectURL(blob);
                    link.download = row.name;
                    link.click();
                    URL.revokeObjectURL(link.href);
                })
                .catch(err => {
                    this.$Loading.error();
                    this.$Notice.error({
                        title: "下载失败",
                        desc: "错误详情：<br/>" + err
                    });
                    console.error(err);
                });
        },
        search() {
            if (!this.path.endsWith("/") && this.path != "")
                this.path = this.path + "/";
            this.loading = true;
            axios
                .get("/api/repositories/" + this.repository + "/" + this.path)
                .then(res => {
                    this.data = _(res.data)
                        .uniqBy("name")
                        .map(i => {
                            i.open = false;
                            i.loading = false;
                            i.pom = {};
                            if (!Number.isInteger(i.size)) return i;
                            let unit = {
                                bytes: 0,
                                KiB: 1,
                                MiB: 2,
                                GiB: 3,
                                TiB: 4
                            };
                            i.size = this.formatBytes(i.size);
                            return i;
                        })
                        .orderBy('type', 'desc')
                        .value();
                    if (this.path != "") {
                        this.data.unshift({
                            type: "folder",
                            name: "..",
                            size: "-",
                            updated_at: "-"
                        });
                    }
                    this.loading = false;
                })
                .catch(err => {
                    this.loading = false;
                });
        },
        formatBytes(bytes, decimals = 2) {
            if (bytes === 0) return "0 bytes";

            const k = 1024;
            const dm = decimals < 0 ? 0 : decimals;
            const sizes = [
                "bytes",
                "KB",
                "MB",
                "GB",
                "TB",
                "PB",
                "EB",
                "ZB",
                "YB"
            ];

            const i = Math.floor(Math.log(bytes) / Math.log(k));

            return (
                parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) +
                " " +
                sizes[i]
            );
        },
        copy(row, all, type) {
            var artifact = row.pom;
            if (type == "maven") {
                var text = `        <dependency>
            <groupId>${artifact.groupId}</id>
            <artifactId>${artifact.artifactId}</artifactId>
            <version>${artifact.version}</version>
        </dependency>`;
                if (all) {
                    text =
                        "    <dependencies>\n" +
                        text +
                        "\n        <!-- Other dependencies -->\n    </dependencies>";
                }
            } else if (type == "gradle") {
                var text = `    compileOnly group: '${artifact.groupId}', name: '${artifact.artifactId}', version: '${artifact.version}'`;
            }
            navigator.clipboard.writeText(text);
            this.$Notice.success({
                title: "复制成功"
            });
            row.open = false;
        },
        maven(row) {
            this.$Loading.start();
            /*
            this.$Notice.info({
                title: "解析中……",
                desc: "请稍等"
            });
            */
            row.open = true;
            row.loading = true;
            axios
                .get(row.full)
                .then(res => {
                    this.$Loading.finish();
                    row.loading = false;
                    var parser = new DOMParser().parseFromString(
                        res.data,
                        "text/xml"
                    );
                    let parseDom = name => {
                        if (parser.querySelector(name) == undefined)
                            return "";
                        return parser.querySelector(name).textContent;
                    };
                    row.pom = {
                        groupId: parseDom("project > groupId"),
                        artifactId: parseDom("project > artifactId"),
                        version: parseDom("project > version"),
                        name: parseDom("project > name"),
                        description: parseDom("project > description")
                    };
                })
                .catch(err => {
                    this.$Loading.error();
                    this.$Notice.error({
                        title: "解析失败",
                        desc: "错误详情：<br/>" + err
                    });
                    console.error(err);
                });
        }
    },
    mounted() {
        this.search();
    },
    data() {
        return {
            path: "",
            loading: false,
            columns: [
                {
                    title: "",
                    key: "type",
                    slot: "type",
                    width: 32
                },
                {
                    title: "文件名",
                    key: "name"
                },
                {
                    title: "大小",
                    key: "size",
                    width: 120
                },
                {
                    title: "更新时间",
                    slot: "updated_at",
                    width: 250
                },
                {
                    title: "操作",
                    slot: "action",
                    width: 150
                }
            ],
            data: []
        };
    }
};
</script>
<style>
.wrapper {
    position: relative;
}
.file-browser {
    width: 100%;
}
.ivu-input {
    outline: 0;
    border: none;
    border-bottom: 2px var(--gray) solid;
}
.ivu-input, .ivu-input-group-append, .ivu-input-group-prepend {
    border-radius: 0 !important;
}
.ivu-modal-header {
    border-bottom: none;
}
.ivu-modal-footer {
    border-top: none;
}
.modal-action {
    text-align: right;
}
</style>
